package com.direct.ssh.dao.impl;

import java.io.Serializable;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Types;
import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;

import com.direct.ssh.common.SystemConstant;
import com.direct.ssh.dao.BaseDao;
import com.direct.ssh.domain.Entity;

/**
 * @author Direct
 *
 * @param <T>
 */
public abstract class BaseDaoImpl<T> implements BaseDao<T> {

	private SessionFactory sessionFactory;
	
	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}
	
	protected Session getSession() {
		return sessionFactory.getCurrentSession();
	}
	
	public void add(T t) {
		getSession().save(t);
	}

	public void update(T t) {
		getSession().update(t);
	}

	public void delete(T t) {

		Entity e = (Entity) getSession().load(t.getClass(), ((Entity) t).getId());

		e.setValid(SystemConstant.INVALID);

		update((T)e);
	}

	public T queryById(Class c,Serializable id) {
		return (T) getSession().get(c, id);
	}

	public T querySingle(String hql, Object[] params) {
		return (T) getQuery(hql, params).uniqueResult();
	}

	public long queryCount(String hql, Object[] params) {

		StringBuilder hqlBuilder = new StringBuilder();
		hqlBuilder.append("select count(*) from ( ");
		hqlBuilder.append(hql);
		hqlBuilder.append(" ) ");

		return (Long) getQuery(hqlBuilder.toString(), params).iterate().next();
	}

	public List<T> queryList(String hql, Object[] params) {
		return getQuery(hql, params).list();
	}

	public List<T> queryList(String hql, Object[] params, int pn, int pr) {
		Query query = getQuery(hql, params);
		
		query.setFirstResult(((pn-1)*pr) + 1);
		query.setMaxResults(pr);
		
		return query.list();
	}
	
	private Query getQuery(String hql,Object[] params) {
		Session session = getSession();
		
		session.enableFilter("validFilter").setParameter("valid", SystemConstant.VALID);
		
		Query query = session.createQuery(hql);
		if(params != null && params.length > 0) {
			for (int i = 0; i < params.length; i++) {
				query.setParameter(i, params[i]);
			}
		}
		return query;
	}
	
	/**
	 * 获得订单流水号
	 * @return
	 */
	protected String getSerialOrderNumber() {
		
		Connection conn = null;
		CallableStatement cs = null;
		
		try {
			conn = getSession().disconnect();
			cs = conn.prepareCall("{call pro_order_serialnumber(?)}");
			cs.registerOutParameter(1, Types.VARCHAR);
			cs.execute();
			return cs.getString(1);
			
		} catch(SQLException e) {
			throw new RuntimeException("执行过程出错了!", e);
		} finally {
			
			try {
				if(cs != null) {
					cs.close();
				}
				if(conn != null) {
					conn.close();
				}
			} catch (SQLException e) {
				throw new RuntimeException("执行过程出错", e);
			}
		}
	}
	
}
